<?php

namespace App\Services\Admin\SuperAdmin;

use App\Exceptions\SuperAdminException;
use App\Models\Admin\Authority\AuthoritiesModel;
use Exception;
use Illuminate\Support\Facades\DB;

class AuthorityService extends BaseSuperAdminService
{

    /**
     * 创建角色
     *
     * @param array $params
     * @return array
     * @throws Exception
     */
    public function createAuthority(array $params): array
    {
        $createAuthorityData = [
            'name' => $params['authorityName'],
            'parent_id' => $params['parentId'] ?? 0,
            'default_router' => AuthoritiesModel::DEFAULT_ROUTER_DEFAULT,
        ];

        // 查询默认
        $menusInfo = $this->getMenusModel()->getItemByName(AuthoritiesModel::DEFAULT_ROUTER_DEFAULT);

        $authorityId = 0;
        DB::transaction(function () use ($createAuthorityData, $menusInfo, &$authorityId) {
            // 添加角色
            $authorityId = $this->getAuthoritiesModel()->addItemGetId($createAuthorityData);
            // 添加角色 默认菜单关联信息
            $this->getAuthorityMenusModel()->addItem([
                'menu_id' => $menusInfo['id'],
                'authority_id' => $authorityId,
            ]);
        });

        return [
            'authorityId' => $authorityId,
        ];
    }

    /**
     * 更新角色
     *
     * @param array $params
     * @return void
     * @throws SuperAdminException
     */
    public function updateAuthority(array $params): void
    {
        // 查询角色
        $authorityInfo = $this->getAuthoritiesModel()->getItemById($params['authorityId'], [
            'id', 'name', 'parent_id',
        ]);
        if (empty($authorityInfo)) {
            throw new SuperAdminException('角色不存在', SuperAdminException::CODE_1007);
        }

        $updateData = [];
        if ($params['parentId'] != $authorityInfo['parent_id']) {
            $updateData['parent_id'] = $params['parentId'];
        }
        if ($params['authorityName'] != $authorityInfo['name']) {
            $updateData['name'] = $params['authorityName'];
        }

        $updateData && $this->getAuthoritiesModel()->updateItemById($params['authorityId'], $updateData);
    }

    /**
     * 删除角色
     *
     * @param array $params
     * @return void
     * @throws SuperAdminException
     */
    public function deleteAuthority(array $params): void
    {
        // 查询角色
        $authorityInfo = $this->getAuthoritiesModel()->getItemById($params['authorityId'], [
            'id', 'name', 'parent_id',
        ]);
        if (empty($authorityInfo)) {
            throw new SuperAdminException('角色不存在', SuperAdminException::CODE_1007);
        }

        // 查询用户是否使用角色
        $userAuthority = $this->getUserAuthorityModel()->getItemByAuthorityId($params['authorityId'], ['user_id', 'authority_id']);
        if (!empty($userAuthority)) {
            throw new SuperAdminException('此角色有用户正在使用，禁止删除', SuperAdminException::CODE_1008);
        }

        // 查询是否有子角色
        $isSubAuthority = $this->getAuthoritiesModel()->getItemByParentId($params['authorityId']);
        if ($isSubAuthority) {
            throw new SuperAdminException('此角色存在子角色，不允许删除', SuperAdminException::CODE_1009);
        }

        DB::transaction(function () use ($params) {
            // 删除角色关联菜单
            $this->getAuthorityMenusModel()->deleteItemByAuthorityId($params['authorityId']);
            // 删除角色关联按钮
            $this->getAuthorityButtonModel()->deleteItemByAuthorityId($params['authorityId']);
            // 删除角色
            $this->getAuthoritiesModel()->deleteItemById($params['authorityId']);
        });
    }

    /**
     * 角色列表
     *
     * @return array
     * @throws Exception
     */
    public function authorityList(): array
    {
        // 查询角色列表
        $authorityList = $this->getAuthoritiesModel()->list([
            'id as authorityId', 'parent_id as parentId', 'name as authorityName',
        ]);

        // 查询非根角色列表
        $list = $this->_authorityListHandle($authorityList);

        return [
            'list' => $list,
        ];
    }

    private function _authorityListHandle(array $list): array
    {
        $rootList = [];
        foreach ($list as $index => $item) {
            if ($item['parentId'] == 0) {
                $rootList[] = $item;
                unset($list[$index]);
            }
        }

        foreach ($rootList as $index => $item) {
            $rootList[$index]['children'] = $this->_childrenAuthorityListHandle($item['authorityId'], $list);
        }

        return $rootList;
    }

    private function _childrenAuthorityListHandle(int $parentId, array $list): array
    {
        $resultList = [];
        foreach ($list as $key => $item) {
            unset($list[$key]);
            if ($item['parentId'] == $parentId) {
                $item['children'] = $this->_childrenAuthorityListHandle($item['authorityId'], $list);
                $resultList[] = $item;
            }
        }
        return $resultList;
    }
}
